package com.fans.admin.generator.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.velocity.VelocityContext;

import com.fans.admin.generator.entity.ColumnInfo;
import com.fans.admin.generator.entity.TableInfo;
import com.fans.admin.generator.properties.GenProperties;
import com.fans.common.constant.SysConstant;
import com.fans.common.utils.DateUtils;
import com.fans.common.utils.SpringUtil;
import com.fans.common.utils.StringUtils;

/**
 * 代码生成器 工具类
 * 
 * @author fanhaohao
 */
public class GenUtils
{
    /** 项目空间路径 */
    private static final String PROJECT_PATH = getProjectPath();

	/** COMMON空间路径 */
	private static final String COMMON_PATH = "common";

    /** html空间路径 */
	private static final String TEMPLATES_PATH = "page/views";

    /** 类型转换 */
    public static Map<String, String> javaTypeMap = new HashMap<String, String>();

	/** 接口提供者包路径 */
	private static final String PROVIDER_PATH_PRE = "provider";

	/** 接口消费者包路径*/
	private static final String CONSUMER_PATH_PRE = "consumer";

    /**
     * 
     * @Title：getGenProperties  
     * @Description: 获取 GenProperties
     * @author: fanhaohao
     * @date 2020年1月17日 下午4:03:20 
     * @param @return 
     * @return GenProperties 
     * @throws
     */
	public static GenProperties getGenProperties() {
		return SpringUtil.getBean(GenProperties.class);
	}

    /**
     * 设置列信息
     */
    public static List<ColumnInfo> transColums(List<ColumnInfo> columns)
    {
        // 列信息
        List<ColumnInfo> columsList = new ArrayList<>();
        for (ColumnInfo column : columns)
        {
            // 列名转换成Java属性名
            String attrName = StringUtils.convertToCamelCase(column.getColumnName());
            column.setAttrName(attrName);
            column.setAttrname(StringUtils.uncapitalize(attrName));

            // 列的数据类型，转换成Java类型
            String attrType = javaTypeMap.get(column.getDataType());
            column.setAttrType(attrType);

            columsList.add(column);
        }
        return columsList;
    }

    /**
     * 获取模板信息
     * 
     * @return 模板列表
     */
    public static VelocityContext getVelocityContext(TableInfo table)
    {
        // java对象数据传递到模板文件vm
        VelocityContext velocityContext = new VelocityContext();
		String packageName = getGenProperties().getPackageName();
		velocityContext.put("tableName", table.getTableName()); // 表名
		velocityContext.put("tableComment", replaceKeyword(table.getTableComment())); // 表备注
		velocityContext.put("primaryKey", table.getPrimaryKey()); // 主键
		velocityContext.put("className", table.getClassName());// 如Gen
		velocityContext.put("classname", table.getClassname());// 如gen
		velocityContext.put("controllerName", table.getClassName() + "Controller"); // 如GenController
		velocityContext.put("IServiceName", "I" + table.getClassName() + "Service"); // 如IGenService
		velocityContext.put("servicename", table.getClassname() + "Service"); // 如genService
		velocityContext.put("serviceName", table.getClassName() + "ServiceImpl"); // 如GenServiceImpl
        velocityContext.put("columns", table.getColumns());
        velocityContext.put("moduleName", getModuleName(packageName)); //模块名 com.fans.admin.test  test 为模块名
        velocityContext.put("basePackage", getBasePackage(packageName)); //基础路径 com.fans.admin.test   com.fans.admin 为基础路径 
		velocityContext.put("package", packageName); // 基础路径 com.fans.admin.test
		velocityContext.put("author", getGenProperties().getAuthor()); // 作者
		velocityContext.put("datetime", DateUtils.getDate()); // 创建时间
		velocityContext.put("version", getGenProperties().getVersion()); // 创建版本
		velocityContext.put("copyright", getGenProperties().getCopyright()); // 版权
		velocityContext.put("enableCache", getGenProperties().getEnableCache()); // 是否开启缓存
		velocityContext.put("apiPrefix", "v1"); // 统一接口前缀（访问 /v1/../..）
		velocityContext.put("superEntityClass", "BaseEntity");//entity 父包
		velocityContext.put("superEntityClassPackage", "com.fans.common.base.BaseEntity");//entity 父包 路径
		velocityContext.put("superMapperClass", "BaseMapper");//mapper 父包
		velocityContext.put("superMapperClassPackage", "com.baomidou.mybatisplus.mapper.BaseMapper");//mapper 父包 路径
		velocityContext.put("superServiceClass", "IService");//service 父包
		velocityContext.put("superServiceClassPackage", "com.baomidou.mybatisplus.service.IService");//service 父包 路径
		velocityContext.put("superServiceImplClass", "ServiceImpl");//serviceImpl 父包
		velocityContext.put("superServiceImplClassPackage", "com.baomidou.mybatisplus.service.impl.ServiceImpl");//serviceImpl 父包 路径
		velocityContext.put("superControllerClass", "BaseController");//controller 父包
		velocityContext.put("superControllerClassPackage", "com.fans.common.base.BaseController");//controller 父包 路径
		// entity引入包
		List<String> importPackages = new ArrayList<>();
		importPackages.add("");
		velocityContext.put("importPackages", importPackages);
		// uuid
		Map<String, Object> uuidMap = new HashMap<>();
		uuidMap.put("uuid1", UUID.randomUUID().toString().replaceAll("-", ""));
		uuidMap.put("uuid2", UUID.randomUUID().toString().replaceAll("-", ""));
		uuidMap.put("uuid3", UUID.randomUUID().toString().replaceAll("-", ""));
		uuidMap.put("uuid4", UUID.randomUUID().toString().replaceAll("-", ""));
		uuidMap.put("uuid5", UUID.randomUUID().toString().replaceAll("-", ""));
		velocityContext.put("uuid", uuidMap);

        return velocityContext;
    }

    /**
     * 获取模板信息
     * 
     * @return 模板列表
     */
    public static List<String> getTemplates()
    {
        List<String> templates = new ArrayList<String>();
		// 接口提供者controller
		templates.add("templates/provider/controller.java.vm");
		// 接口提供者实体类（和消费者实体类公用）
		templates.add("templates/provider/entity.java.vm");
		// 接口提供者实体类转换类
		templates.add("templates/provider/entityWarpper.java.vm");
		// 接口提供者mapper类
		templates.add("templates/provider/mapper.java.vm");
		// 接口提供者mapper xml
		templates.add("templates/provider/mapper.xml.vm");
		// 接口提供者service
		templates.add("templates/provider/service.java.vm");
		// 接口提供者service实现
		templates.add("templates/provider/serviceImpl.java.vm");
		// 前端页面模板
		templates.add("templates/front/vue.vm");
		// 通用模板（包括了菜单的sql语句等）
		templates.add("templates/common/common.vm");
		// 接口消费者controller
		templates.add("templates/consumer/controller.java.vm");
		// 接口消费者service
		templates.add("templates/consumer/service.java.vm");
		// 接口消费者serviceFallbackImpl
		templates.add("templates/consumer/serviceFallbackImpl.java.vm");

        return templates;
    }

    /**
     * 表名转换成Java类名
     */
    public static String tableToJava(String tableName)
    {
		if (SysConstant.AUTO_REOMVE_PRE.equals(getGenProperties().getAutoRemovePre()))
        {
            tableName = tableName.substring(tableName.indexOf("_") + 1);
        }
		if (StringUtils.isNotEmpty(getGenProperties().getTablePrefix()))
        {
			tableName = tableName.replace(getGenProperties().getTablePrefix(), "");
        }
        return StringUtils.convertToCamelCase(tableName);
    }

    /**
     * 获取文件名
     */
    public static String getFileName(String template, TableInfo table, String moduleName)
    {
        // 小写类名
        String classname = table.getClassname();
        // 大写类名
        String className = table.getClassName();
        String javaPath = PROJECT_PATH;
		String htmlPath = TEMPLATES_PATH + "/" + moduleName;
		// 接口提供者路径
		String providerPath = PROVIDER_PATH_PRE + "/" + javaPath;
		// 接口消费者路径
		String consumerPath = CONSUMER_PATH_PRE + "/" + javaPath;
		// 通用配置路径
		String commonPath = COMMON_PATH + "/";

		if (template.contains("provider/controller.java.vm")) {
			return providerPath + "controller" + "/" + className + "Controller.java";
		}

		if (template.contains("provider/entity.java.vm")) {
			return providerPath + "entity" + "/" + className + ".java";
		}

		if (template.contains("provider/entityWarpper.java.vm"))
        {
			return providerPath + "warpper" + "/" + className + "Warpper.java";
        }

		if (template.contains("provider/mapper.java.vm"))
        {
			return providerPath + "dao" + "/" + className + "Mapper.java";
        }

		if (template.contains("provider/mapper.xml.vm")) {
			return providerPath + "dao" + "/" + "mapper" + "/" + className + "Mapper.xml";
		}

		if (template.contains("provider/service.java.vm"))
        {
			return providerPath + "service" + "/" + "I" + className + "Service.java";
        }

		if (template.contains("provider/serviceImpl.java.vm"))
        {
			return providerPath + "service" + "/impl/" + className + "ServiceImpl.java";
        }

		if (template.contains("vue.vm"))
        {
			return htmlPath + "/" + classname + ".vue";
        }

		if (template.contains("common.vm")) {
			return commonPath + classname + "Common.txt";
		}

		if (template.contains("consumer/controller.java.vm")) {
			return consumerPath + "controller" + "/" + className + "Controller.java";
		}

		if (template.contains("consumer/service.java.vm")) {
			return consumerPath + "feign" + "/" + className + "Service.java";
		}

		if (template.contains("consumer/serviceFallbackImpl.java.vm")) {
			return consumerPath + "feign" + "/" + "fallback" + "/" + className + "ServiceFallbackImpl.java";
		}

        return null;
    }

    /**
     * 获取模块名
     * 
     * @param packageName 包名
     * @return 模块名
     */
    public static String getModuleName(String packageName)
    {
        int lastIndex = packageName.lastIndexOf(".");
        int nameLength = packageName.length();
        String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength);
        return moduleName;
    }

    public static String getBasePackage(String packageName)
    {
        int lastIndex = packageName.lastIndexOf(".");
        String basePackage = StringUtils.substring(packageName, 0, lastIndex);
        return basePackage;
    }

    public static String getProjectPath()
    {
		String packageName = getGenProperties().getPackageName();
        StringBuffer projectPath = new StringBuffer();
        projectPath.append("main/java/");
        projectPath.append(packageName.replace(".", "/"));
        projectPath.append("/");
        return projectPath.toString();
    }

    public static String replaceKeyword(String keyword)
    {
        String keyName = keyword.replaceAll("(?:表|信息)", "");
        return keyName;
    }

    static
    {
        javaTypeMap.put("tinyint", "Integer");
        javaTypeMap.put("smallint", "Integer");
        javaTypeMap.put("mediumint", "Integer");
        javaTypeMap.put("int", "Integer");
        javaTypeMap.put("integer", "integer");
        javaTypeMap.put("bigint", "Long");
        javaTypeMap.put("float", "Float");
        javaTypeMap.put("double", "Double");
        javaTypeMap.put("decimal", "BigDecimal");
        javaTypeMap.put("bit", "Boolean");
        javaTypeMap.put("char", "String");
        javaTypeMap.put("varchar", "String");
        javaTypeMap.put("tinytext", "String");
        javaTypeMap.put("text", "String");
        javaTypeMap.put("mediumtext", "String");
        javaTypeMap.put("longtext", "String");
        javaTypeMap.put("time", "Date");
        javaTypeMap.put("date", "Date");
        javaTypeMap.put("datetime", "Date");
        javaTypeMap.put("timestamp", "Date");
    }
}
